package org.chen.tomcat;

import java.io.*;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Chen
 * @since 2023/6/9 15:47
 */
public class Response extends AbstractHttpServletResponse {

    private int status = 200;

    private String message = "OK";

    private final byte SP = ' ';

    private final byte CR = '\r';

    private final byte LF = '\n';

    private final Map<String, String> headers = new HashMap<>();

    private final Request request;

    private final OutputStream socketOutputStream;

    private final ResponseServletOutPutSteam responseServletOutPutSteam = new ResponseServletOutPutSteam();

    private final PrintWriter writer = new PrintWriter(responseServletOutPutSteam);

    public Response(Request request) throws IOException {
        this.request = request;
        this.socketOutputStream = request.getSocket().getOutputStream();

    }

    @Override
    public void setStatus(int sc, String sm) {
        this.status = sc;
        this.message = sm;
    }

    @Override
    public int getStatus() {
        return status;
    }

    @Override
    public void addHeader(String name, String value) {
        headers.put(name, value);
    }

    @Override
    public String getHeader(String name) {
        return this.headers.get(name);
    }

    @Override
    public ResponseServletOutPutSteam getOutputStream() throws IOException {
        return responseServletOutPutSteam;
    }

    /**
     * 完成响应
     */
    public void complete() {
        //发送响应
        try {
            sendResponseLine();
            sendResponseHeader();
            sendResponseBody();
            socketOutputStream.flush();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 发送响应体
     */
    private void sendResponseBody() throws IOException {
        socketOutputStream.write(getOutputStream().getBody());
    }



    /**
     * 发送响应头
     */
    private void sendResponseHeader() throws IOException {
        if (!headers.containsKey("Content-Length")) {
            headers.put("Content-Length", String.valueOf(getOutputStream().getPos()));
        }
        if (!headers.containsKey("Content-Type")) {
            headers.put("Content-Type", "text/html;charset=utf-8");
        }
        headers.forEach((key, value) -> {
            try {
                socketOutputStream.write(key.getBytes());
                socketOutputStream.write(':');
                socketOutputStream.write(SP);
                socketOutputStream.write(value.getBytes());
                socketOutputStream.write(CR);
                socketOutputStream.write(LF);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
        socketOutputStream.write(CR);
        socketOutputStream.write(LF);
    }

    /**
     * 发送响应行
     */
    private void sendResponseLine() throws IOException {
        //协议
        socketOutputStream.write(request.getProtocol().getBytes());
        socketOutputStream.write(SP);
        //状态码
        socketOutputStream.write(status);
        socketOutputStream.write(SP);
        //状态码描述
        socketOutputStream.write(message.getBytes());
        socketOutputStream.write(CR);
        socketOutputStream.write(LF);
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        return writer;
    }

    @Override
    public void setStatus(int status) {
        this.status = status;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public void setContentType(String type) {
        setHeader("Content-Type", type);
    }

    @Override
    public void setHeader(String name, String value) {
        this.headers.put(name, value);
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
        setStatus(sc);
        setMessage(msg);
        setContentType("text/html");
        String file = ClassLoader.getSystemClassLoader().getResource("error.html").getFile();
        String content = readTemplateFile(file);
        content = content.replace("{{errorCode}}", Integer.toString(sc));
        content = content.replace("{{errorMessage}}", msg);
        getOutputStream().write(content.getBytes());
    }

    // 打开模板文件并读取其中的内容
    private String readTemplateFile(String templateFile) throws IOException {
        FileInputStream inputStream = new FileInputStream(templateFile);
        byte[] buffer = new byte[1024];
        StringBuilder stringBuilder = new StringBuilder();
        while (inputStream.read(buffer) != -1) {
            stringBuilder.append(new String(buffer, StandardCharsets.UTF_8));
        }
        inputStream.close();
        return stringBuilder.toString();
    }
}
